home *** CD-ROM | disk | FTP | other *** search
- /* Routines for the SEGHEAP library */
- /* Copyright (C) Stephen Chung, 1992. */
- /* All rights reserved. */
-
- #include <windows.h>
- #include <stdarg.h>
-
- #define MAGIC 0x42022667
-
- typedef struct MemoryStruct {
- long int magic;
- void far *page;
- unsigned int size;
- BOOL allocated;
- struct MemoryStruct far *next, far *prev;
- } MEMHEADER;
-
- typedef struct PageHeaderStruct {
- long int magic;
- HANDLE handle;
- unsigned int size;
- unsigned int used;
- unsigned int overhead;
- MEMHEADER far *data, far *empty;
- struct PageHeaderStruct far *next, far *prev;
- } MEMPAGEHEADER;
-
- typedef struct {
- MEMPAGEHEADER far *pages;
- int nr_pages;
- } MAINMEMHEADER;
-
- #define PAGESIZE (4 * 1024)
- #define USEABLESIZE (PAGESIZE - sizeof(MEMPAGEHEADER) - sizeof(MEMHEADER))
-
-
- static MAINMEMHEADER header = { NULL, 0 };
-
-
-
- static void Error(char *fmt, ...)
- {
- va_list argptr;
- char buffer[1024];
-
- va_start(argptr, fmt);
- vsprintf(buffer, fmt, argptr);
- va_end(argptr);
-
- MessageBeep(0);
- MessageBox (NULL, buffer, "Error Message", MB_ICONEXCLAMATION | MB_OK);
- }
-
-
-
- static MEMPAGEHEADER far *AddPage(unsigned int n)
- {
- void far *cp;
- MEMHEADER far *mp;
- MEMPAGEHEADER far *p;
- HANDLE handle = NULL;
-
- handle = GlobalAlloc(GMEM_MOVEABLE, n);
- if (handle == NULL) {
- Error("Out of memory: allocating %d bytes", n);
- return (NULL);
- }
-
- if (header.pages == NULL || header.nr_pages <= 0) {
- p = header.pages = (MEMPAGEHEADER far *) GlobalLock(handle);
- p->prev = NULL;
- } else {
- for (p = header.pages; p->next != NULL; p = p->next);
- p->next = (MEMPAGEHEADER far *) GlobalLock(handle);
- p->next->prev = p;
- p = p->next;
- }
-
- p->magic = MAGIC;
- p->handle = handle;
- p->next = NULL;
- p->size = n;
- p->used = 0;
- p->overhead = sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER);
-
- cp = ((char far *) p) + sizeof(MEMPAGEHEADER);
- mp = (MEMHEADER far *) cp;
-
- p->data = p->empty = mp;
-
- mp->magic = 0L;
- mp->allocated = FALSE;
- mp->page = p;
- mp->size = p->size - p->overhead;
- mp->next = mp->prev = NULL;
-
- header.nr_pages++;
-
- return (p);
- }
-
-
-
- static void DeletePage (MEMPAGEHEADER far *p)
- {
- if (p->next == NULL && p->prev == NULL) {
- header.pages = NULL;
- header.nr_pages = 0;
- GlobalFree(GlobalUnlock(p->handle));
- } else {
- if (p == header.pages) header.pages = p->next;
- header.nr_pages--;
-
- if (p->prev != NULL) p->prev->next = p->next;
- if (p->next != NULL) p->next->prev = p->prev;
-
- GlobalFree(GlobalUnlock(p->handle));
- }
- }
-
-
-
- void far *SegHeapAlloc (unsigned int n)
- {
- MEMPAGEHEADER far *p;
- MEMHEADER far *mp;
- char far *cp;
-
- if (n >= 65535) {
- Error("MyGlobalAlloc: size (%ud) > 64K!", n);
- return (NULL);
- }
-
- /* Larger than page size? */
-
- if (n > USEABLESIZE) {
- p = AddPage(n + sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER));
-
- mp = p->data;
- mp->magic = MAGIC;
- mp->allocated = TRUE;
-
- p->used = n;
- p->empty = NULL;
-
- cp = ((char far *) mp) + sizeof(MEMHEADER);
- return ((void far *) cp);
- }
-
-
- /* Search for the hole */
-
- for (p = header.pages; p != NULL; p = p->next) {
- /* Scan the chains */
- if (p->size - p->used - p->overhead <= 0) continue;
- if (p->empty == NULL) continue;
-
- for (mp = p->empty; mp != NULL; mp = mp->next) {
- if (!mp->allocated && mp->size >= n) break;
- }
-
- if (mp != NULL) break;
- }
-
- /* New page needed? */
-
- if (p == NULL) {
- p = AddPage(PAGESIZE);
- mp = p->data;
- }
-
- /* Do we need to break it up? */
-
- if (mp->size - n > sizeof(MEMHEADER)) {
- MEMHEADER far *mp2;
-
- cp = ((char far *) mp) + n + sizeof(MEMHEADER);
- mp2 = (MEMHEADER far *) cp;
-
- mp2->magic = 0L;
- mp2->allocated = FALSE;
- mp2->page = p;
- mp2->size = mp->size - n - sizeof(MEMHEADER);
-
- mp2->next = mp->next;
- mp2->prev = mp;
- if (mp->next != NULL) mp->next->prev = mp2;
- mp->next = mp2;
-
-
- p->overhead += sizeof(MEMHEADER);
-
- mp->size = n;
- }
-
- mp->magic = MAGIC;
- mp->allocated = TRUE;
-
- p->used += n;
- cp = ((char far *) mp) + sizeof(MEMHEADER);
-
- /* Search for the next empty hole */
-
- for (; mp != NULL; mp = mp->next) {
- if (!mp->allocated && mp->size > 0) break;
- }
-
- p->empty = mp;
-
- return ((void far *) cp);
- }
-
-
- void SegHeapFree (void far *vp)
- {
- MEMPAGEHEADER far *p;
- MEMHEADER far *mp, far *mp2;
- char far *cp;
-
- cp = ((char far *) vp) - sizeof(MEMHEADER);
- mp = (MEMHEADER far *) cp;
-
- if (mp->magic != MAGIC || !mp->allocated) {
- Error("Trying to deallocate invalid memory block (%Fp)!\n", cp);
- return;
- }
-
- p = (MEMPAGEHEADER far *) mp->page;
- p->used -= mp->size;
-
- mp->magic = 0L;
- mp->allocated = FALSE;
-
- /* Merge? */
-
- mp2 = mp->prev;
-
- if (mp2 != NULL && !mp2->allocated) {
- mp2->next = mp->next;
- if (mp->next != NULL) mp->next->prev = mp2;
- mp2->size += mp->size + sizeof(MEMHEADER);
-
- p->overhead -= sizeof(MEMHEADER);
-
- mp = mp2;
- }
-
- mp2 = mp->next;
-
- if (mp2 != NULL && !mp2->allocated) {
- mp->next = mp2->next;
- if (mp2->next != NULL) mp2->next->prev = mp;
-
- mp->size += mp2->size + sizeof(MEMHEADER);
-
- p->overhead -= sizeof(MEMHEADER);
- }
-
- if (mp->prev == NULL && mp->next == NULL) {
- DeletePage(p);
- } else {
- if (p->empty == NULL || p->empty < mp) p->empty = mp;
- }
- }
-
-
-
- void far *SegHeapRealloc (void far *p, unsigned int n)
- {
- MEMHEADER far *mp;
- char far *cp;
-
- /* Block already large enough? */
-
- cp = ((char far *) p) - sizeof(MEMHEADER);
- mp = (MEMHEADER far *) cp;
-
- if (mp->magic != MAGIC) {
- Error("Error: Trying to reallocate invalid memory block!");
- return (p);
- }
-
- if (mp->size >= n) return (p); /* No need to do anything */
-
- /* Else swap to another block */
-
- cp = SegHeapAlloc(n);
- memcpy(cp, p, (mp->size >= n) ? n : mp->size);
- SegHeapFree(p);
-
- return ((void far *) cp);
- }
-
-
-
- void MemoryStatistics (long int *allocated, long int *used)
- {
- MEMPAGEHEADER far *p;
-
- *allocated = *used = 0L;
-
- for (p = header.pages; p != NULL; p = p->next) {
- *allocated += p->size;
- *used += p->used + p->overhead;
- }
- }
-
-
- void FreeAllMemory (void)
- {
- MEMPAGEHEADER far *p, far *p1;
-
- for (p = header.pages; p != NULL; ) {
- p1 = p->next;
- GlobalFree(GlobalUnlock(p->handle));
- p = p1;
- }
-
- header.pages = NULL;
- header.nr_pages = 0;
- }
-
-
- #ifdef DEBUG
-
- /* For debugging purposes... not very pretty */
-
- void PrintMemoryChains(void)
- {
- MEMPAGEHEADER far *p;
- MEMHEADER far *mp;
- char far *cp;
- char buffer[100];
-
- /* Block already large enough? */
-
-
- for (p = header.pages; p != NULL; p = p->next) {
- for (mp = p->data; mp != NULL; mp = mp->next) {
- sprintf(buffer, "%Fp | %ud | %s", mp, mp->size, mp->allocated ? "Alloc" : "Free");
- MessageBox (NULL, buffer, "Memory Chain", MB_ICONEXCLAMATION | MB_OK);
- }
- }
- }
-
- #endif DEBUG
-